﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using Core.Primitives;

namespace Core
{
    [Serializable]
    public class DataField
    {
        private Matrix<DataPoint> m_values;
        public Matrix<DataPoint> Values
        {
            get
            {
                return m_values;
            }
        }

        private float m_stepX;
        public float StepX
        {
            get { return m_stepX; }
        }

        private float m_stepY;
        public float StepY
        {
            get { return m_stepY; }
        }

        private float m_startX;
        public float StartX
        {
            get { return m_startX; }
        }

        private float m_startY;
        public float StartY
        {
            get { return m_startY; }
        }

        public IntSize Size
        {
            get
            {
                return m_values.Size;
            }
        }
        public SingleRect BoundingRectangle
        {
            get
            {
                float width = m_stepX * Size.Width;
                float height = m_stepY * Size.Height;

                return new SingleRect(new SinglePoint(m_startX, m_startY), width, height);
            }
        }

        public DataField (
            int width, 
            int height, 
            float stepX = 1f, 
            float stepY = 1f, 
            float startX = 0f, 
            float startY = 0f)
        {
            m_values = new Matrix<DataPoint>(height, width);

            m_stepX = stepX;
            m_stepY = stepY;

            m_startX = startX;
            m_startY = startY;
        }
        public static DataField FromTypesArray(int[,] types, float stepX = 1, float stepY = 1, float startX = 0, float startY = 0)
        {
            int h = types.GetLength(0);
            int w = types.GetLength(1);

            DataField field = new DataField(w, h, stepX, stepY, startX, startY);

            for (int i = 0; i < h; i++)
            {
                for (int j = 0; j < w; j++)
                {
                    field[i, j] = new DataPoint(types[i, j]);
                }
            }

            return field;
        }

        public DataPoint this[int row, int col]
        {
            get
            {
                return m_values[row, col];
            }

            set
            {
                value.DiscretePosition = new IntPosition(row, col);

                value.Position = new SinglePoint(
                    StepX * col + StartX,
                    StepY * row + StartY);
                
                m_values[row, col] = value;
            }
        }
        public DataPoint this[IntPosition pos]
        {
            get
            {
                return this[pos.Row, pos.Column];
            }

            set
            {
                this[pos.Row, pos.Column] = value;
            }
        }

        public void Save(Stream stream)
        {
            BinaryFormatter formatter = new BinaryFormatter();

            formatter.Serialize(stream, this);
        }
        public static DataField Load(Stream stream)
        {
            BinaryFormatter formatter = new BinaryFormatter();

            return (DataField)formatter.Deserialize(stream);
        }
    }
}
